package com.bumptech.glide.request;

import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.Option;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
import ohos.agp.components.element.Element;
import ohos.media.image.PixelMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Provides type independent options to customize loads with Glide.
 *
 * <p>Non-final to allow Glide's generated classes to be assignable to their non-generated
 * equivalents.
 */
@SuppressWarnings("PMD.UseUtilityClass")
public class RequestOptions extends BaseRequestOptions<RequestOptions> {

  @Nullable private static RequestOptions skipMemoryCacheTrueOptions;
  @Nullable private static RequestOptions skipMemoryCacheFalseOptions;
  @Nullable private static RequestOptions fitCenterOptions;
  @Nullable private static RequestOptions centerInsideOptions;
  @Nullable private static RequestOptions centerCropOptions;
  @Nullable private static RequestOptions circleCropOptions;
  @Nullable private static RequestOptions noTransformOptions;
  @Nullable private static RequestOptions noAnimationOptions;

  /** Returns a {@link RequestOptions} object with {@link #sizeMultiplier(float)} set.
   * @param sizeMultiplier sizemultiplier
   * @return requestoptions
   */
  @SuppressWarnings("WeakerAccess") // Public API  
  @NotNull
  public static RequestOptions sizeMultiplierOf(
       float sizeMultiplier) {
    return new RequestOptions().sizeMultiplier(sizeMultiplier);
  }

  /**
   * Returns a {@link RequestOptions} object with {@link #diskCacheStrategy(DiskCacheStrategy)} set.
   * @param diskCacheStrategy diskcacheStrategy
   * @return requestoptionss
   */
  @NotNull
  public static RequestOptions diskCacheStrategyOf(@NotNull DiskCacheStrategy diskCacheStrategy) {
    return new RequestOptions().diskCacheStrategy(diskCacheStrategy);
  }

  /**
   * Returns a {@link RequestOptions} object with {@link BaseRequestOptions#priority(Priority)}}
   * set.
   * @param priority
   * @return requestoptions
   */
  @SuppressWarnings("WeakerAccess") // Public API  
  @NotNull
  public static RequestOptions priorityOf(@NotNull Priority priority) {
    return new RequestOptions().priority(priority);
  }

  /** Returns a {@link RequestOptions} object with {@link #placeholder(Element)} set.
   * @param placeholder placeholder
   * @return requestoptions
   */
  @NotNull
  public static RequestOptions placeholderOf(@Nullable Element placeholder) {
    return new RequestOptions().placeholder(placeholder);
  }

  /** Returns a {@link RequestOptions} object with {@link #placeholder(int)} set.
   * @param placeholderId
   * @return requestoptions
   */
  @NotNull
  public static RequestOptions placeholderOf( int placeholderId) {
    return new RequestOptions().placeholder(placeholderId);
  }

  /** Returns a {@link RequestOptions} object with {@link #error(Element)} set.
   * @param errorDrawable
   * @return request options
   */
  @NotNull
  public static RequestOptions errorOf(@Nullable Element errorDrawable) {
    return new RequestOptions().error(errorDrawable);
  }

  /** Returns a {@link RequestOptions} object with {@link #error(int)}} set.
   * @param errorId
   * @return request options
   */
  @NotNull
  public static RequestOptions errorOf( int errorId) {
    return new RequestOptions().error(errorId);
  }

  /** Returns a {@link RequestOptions} object with {@link #skipMemoryCache(boolean)} set.
   * @param skipMemoryCache
   * @return request options
   */
  @NotNull
  public static RequestOptions skipMemoryCacheOf(boolean skipMemoryCache) {
    if (skipMemoryCache) {
      if (skipMemoryCacheTrueOptions == null) {
        skipMemoryCacheTrueOptions = new RequestOptions().skipMemoryCache(true).autoClone();
      }
      return skipMemoryCacheTrueOptions;
    } else {
      if (skipMemoryCacheFalseOptions == null) {
        skipMemoryCacheFalseOptions = new RequestOptions().skipMemoryCache(false).autoClone();
      }
      return skipMemoryCacheFalseOptions;
    }
  }

  /** Returns a {@link RequestOptions} object with {@link #override(int, int)}} set.
   * @param width
   * @param height
   * @return request options
   * */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions overrideOf(int width, int height) {
    return new RequestOptions().override(width, height);
  }

  /**
   * Returns a {@link RequestOptions} with {@link #override(int, int)} set where both the width and
   * height are the given size.
   * @param size size
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions overrideOf(int size) {
    return overrideOf(size, size);
  }

  /** Returns a {@link RequestOptions} object with {@link #signature} set.
   * @param signature signature
   * @return  request options
   */
  @NotNull
  public static RequestOptions signatureOf(@NotNull Key signature) {
    return new RequestOptions().signature(signature);
  }

  /** Returns a {@link RequestOptions} object with {@link #fitCenter()} set.
   * @return request options
   */
  @NotNull
  public static RequestOptions fitCenterTransform() {
    if (fitCenterOptions == null) {
      fitCenterOptions = new RequestOptions().fitCenter().autoClone();
    }
    return fitCenterOptions;
  }

  /** Returns a {@link RequestOptions} object with {@link #centerInside()} set.
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions centerInsideTransform() {
    if (centerInsideOptions == null) {
      centerInsideOptions = new RequestOptions().centerInside().autoClone();
    }
    return centerInsideOptions;
  }

  /** Returns a {@link RequestOptions} object with {@link #centerCrop()} set.
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions centerCropTransform() {
    if (centerCropOptions == null) {
      centerCropOptions = new RequestOptions().centerCrop().autoClone();
    }
    return centerCropOptions;
  }

  /** Returns a {@link RequestOptions} object with {@link RequestOptions#circleCrop()} set.
   * @return request options */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions circleCropTransform() {
    if (circleCropOptions == null) {
      circleCropOptions = new RequestOptions().circleCrop().autoClone();
    }
    return circleCropOptions;
  }

  /** Returns a {@link RequestOptions} object with {@link #transform(Transformation)} set.
   * @param transformation
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions bitmapTransform(@NotNull Transformation<PixelMap> transformation) {
    return new RequestOptions().transform(transformation);
  }

  /** Returns a {@link RequestOptions} object with {@link #dontTransform()} set.
   * @return request options
   */
  @SuppressWarnings("WeakerAccess")
  @NotNull
  public static RequestOptions noTransformation() {
    if (noTransformOptions == null) {
      noTransformOptions = new RequestOptions().dontTransform().autoClone();
    }
    return noTransformOptions;
  }

  /**
   * Returns a {@link RequestOptions} object with the given {@link Option} set via {@link
   * #set(Option, Object)}.
   * @param  option
   * @param value
   * @return request options
   */
  @NotNull
  public static <T> RequestOptions option(@NotNull Option<T> option, @NotNull T value) {
    return new RequestOptions().set(option, value);
  }

  /** Returns a {@link RequestOptions} object with {@link #decode(Class)} set.
   * @param resourceClass
   * @return request options
   */
  @NotNull
  public static RequestOptions decodeTypeOf(@NotNull Class<?> resourceClass) {
    return new RequestOptions().decode(resourceClass);
  }

  /** Returns a {@link RequestOptions} object with {@link #format(DecodeFormat)} set.
   * @param format
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions formatOf(@NotNull DecodeFormat format) {
    return new RequestOptions().format(format);
  }

  /** Returns a {@link RequestOptions} object with {@link #frame(long)} set.
   * @param frameTimeMicros
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions frameOf( long frameTimeMicros) {
    return new RequestOptions().frame(frameTimeMicros);
  }

  /** Returns a {@link RequestOptions} object with {@link #downsample(DownsampleStrategy)} set.
   * @param strategy
   * @return request optiosn
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions downsampleOf(@NotNull DownsampleStrategy strategy) {
    return new RequestOptions().downsample(strategy);
  }

  /** Returns a {@link RequestOptions} object with {@link #timeout(int)} set.
   * @param timeout
   * @return request options
   */
  @NotNull
  public static RequestOptions timeoutOf(int timeout) {
    return new RequestOptions().timeout(timeout);
  }

  /**
   * Returns a {@link com.bumptech.glide.request.RequestOptions} with {@link #encodeQuality(int)}
   * called with the given quality.
   * @param quality
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions encodeQualityOf( int quality) {
    return new RequestOptions().encodeQuality(quality);
  }


  /**
   * Returns a new {@link com.bumptech.glide.request.RequestOptions} with {@link #dontAnimate()}
   * called.
   * @return request options
   */
  @SuppressWarnings("WeakerAccess") // Public API
  @NotNull
  public static RequestOptions noAnimation() {
    if (noAnimationOptions == null) {
      noAnimationOptions = new RequestOptions().dontAnimate().autoClone();
    }
    return noAnimationOptions;
  }
}
